package com.zyx.wanshu.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zyx.wanshu.entity.*;
import com.zyx.wanshu.mapper.RoleMapper;
import com.zyx.wanshu.service.IMenuService;
import com.zyx.wanshu.service.IRoleMenuService;
import com.zyx.wanshu.service.IRoleService;
import com.zyx.wanshu.service.IUserRoleService;
import com.zyx.wanshu.util.Query;
import com.zyx.wanshu.vo.RoleMenuVO;
import com.zyx.wanshu.vo.RoleVO;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.stream.Collectors;

/**
 * @author zyx
 * @since 2022/7/15 22:23
 */
@Service
public class RoleServiceImpl extends ServiceImpl<RoleMapper, Role> implements IRoleService {

    @Autowired
    IUserRoleService userRoleService;

    @Autowired
    IRoleMenuService roleMenuService;

    @Autowired
    IMenuService menuService;

    @Override
    public RoleVO search(RoleVO vo) {
        LambdaQueryWrapper<Role> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.like(StrUtil.isNotBlank(vo.getKey()), Role::getRoleName, vo.getKey())
                .or().like(StrUtil.isNotBlank(vo.getKey()), Role::getRoleDesc, vo.getKey())
                .orderByAsc(Role::getOrderRank);
        IPage<Role> page = this.page(
                // 分页信息
                new Query<Role>().getPage(vo.getMap()),
                // 查询条件
                queryWrapper);
        vo.setPage(page);
        return vo;
    }

    /**
     * 判断当前的角色是否能够被删除
     */
    @Override
    public Boolean canIDeleteById(Integer id) {
        Long userRoleCount = userRoleService
                .getBaseMapper()
                .selectCount(new LambdaQueryWrapper<UserRole>().eq(UserRole::getRoleId, id));
        Long roleMenuCount = roleMenuService
                .getBaseMapper()
                .selectCount(new LambdaQueryWrapper<RoleMenu>().eq(RoleMenu::getRoleId, id));
        // 如果都为0 说明这个角色没有被分配，可以删除，否则就不能被删除了
        return userRoleCount == 0 && roleMenuCount == 0;
    }

    @Override
    public List<MenuShowVO> getMenuShow() {
        // 先查询所有的一级菜单
        List<Menu> parentList = menuService.list(new QueryWrapper<Menu>().eq("parent_id", -1));
        // 再根据一级菜单编号找到对应的二级菜单
        return parentList.stream().map(item -> {
            MenuShowVO showVO = new MenuShowVO();
            List<Menu> subMenus = menuService.list(new QueryWrapper<Menu>().eq("parent_id", item.getId()));
            showVO.setSubMenus(subMenus);
            // 根据父菜单的编号查询出对应的信息
            BeanUtils.copyProperties(item, showVO);
            return showVO;
        }).collect(Collectors.toList());
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void allocateMenu(RoleMenuVO vo) {
        // 1.根据角色删除菜单信息
        roleMenuService
                .remove(new LambdaQueryWrapper<RoleMenu>()
                        .eq(RoleMenu::getRoleId, vo.getRoleId()));
        // 2.分配对应的角色和菜单
        List<RoleMenu> list = vo.getMenuIds().stream().map(item -> {
            RoleMenu roleMenu = new RoleMenu();
            roleMenu.setMenuId(item);
            roleMenu.setRoleId(vo.getRoleId());
            return roleMenu;
        }).collect(Collectors.toList());
        // 批量保存角色和菜单的关系
        roleMenuService.saveBatch(list);
    }

    @Override
    public List<Integer> queryMenuByRoleId(Integer roleId) {
        List<RoleMenu> list = roleMenuService
                .list(new LambdaQueryWrapper<RoleMenu>().eq(RoleMenu::getRoleId, roleId));
        if (CollectionUtil.isNotEmpty(list)) {
            return list.stream().map(RoleMenu::getMenuId).collect(Collectors.toList());
        }
        return null;
    }

}
